package duplas;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class PosicionamentoDuplas implements Cloneable{

	List<ArrayList<String>> _posicoes;
	PosicaoSemana _posicaoSemana;
	ArrayList<RestricaoPosicionamento> _restricoes = new ArrayList<RestricaoPosicionamento>();
	
	public void adicionaRestricao(RestricaoPosicionamento restricao) {
		_restricoes.add(restricao);
	}
	
	public void removeRestricao(RestricaoPosicionamento restricao) {
		_restricoes.remove(restricao);
	}
	
	
	public PosicionamentoDuplas(List<ArrayList<String>> posicoes){
		_posicoes = posicoes;
	}
	
	public PosicionamentoDuplas(PosicaoSemana posicaoSemana){
		_posicaoSemana = posicaoSemana;
	}
	
	public List<ArrayList<String>> alocarNovasDuplas(Map<String, String> duplas){
		return alocarNovasDuplas(duplas, _posicaoSemana.getQuemAndou());
	}
	
	public List<ArrayList<String>> alocarNovasDuplas(Map<String, String> duplas, Integer posicaoQueAnda){
		
		for (RestricaoPosicionamento restricao : _restricoes) {
			restricao.aplicarRestricao(_posicoes);
		}
		
		for(List<String> dupla : _posicoes){
			String pessoaQueVaiAndar = escolheQuemAnda(dupla, posicaoQueAnda);
			while (!isAlocadoNoParCorreto(pessoaQueVaiAndar, duplas)) {
				String novoPar = duplas.get(pessoaQueVaiAndar);
				pessoaQueVaiAndar = trocaPosicoesNaDupla(novoPar, pessoaQueVaiAndar);				
			}
		}
		
		return _posicoes;		
	}
	
	public List<ArrayList<String>> alocarNovasDuplas(ArrayList<DuplaSemana> duplas, Integer posicaoQueAnda){
				
		for(List<String> dupla : _posicoes){
			String pessoaQueVaiAndar = escolheQuemAnda(dupla, posicaoQueAnda);
			while (!isAlocadoNoParCorreto(pessoaQueVaiAndar, duplas)) {
				String novoPar = getPar(pessoaQueVaiAndar, duplas);
				pessoaQueVaiAndar = trocaPosicoesNaDupla(novoPar, pessoaQueVaiAndar);				
			}
		}
		
		for (RestricaoPosicionamento restricao : _restricoes) {
			restricao.aplicarRestricao(_posicoes);
		}
		
		return _posicoes;		
	}

	private String trocaPosicoesNaDupla(String pessoaQueNaoMudaLugar, String novaDupla) {
		List<String> par = pegaPar(pessoaQueNaoMudaLugar);
		if (par == null) throw new RuntimeException("Par veio nulo!! " + pessoaQueNaoMudaLugar);
		
		String pessoaQueVaiAndar = null;
		if (par.get(0).equals(pessoaQueNaoMudaLugar)){
			pessoaQueVaiAndar = par.get(1);
			par.remove(1);
			par.add(1, novaDupla);
		} else if (par.get(1).equals(pessoaQueNaoMudaLugar)){
			pessoaQueVaiAndar = par.get(0);
			par.remove(0);
			par.add(0, novaDupla);			
		}
		
		return pessoaQueVaiAndar;
	}

	private boolean isAlocadoNoParCorreto(String pessoaQueVaiAndar,
			Map<String, String> duplas) {
		
		List<String> par = pegaPar(pessoaQueVaiAndar);
		if (par == null) return false;
		
		if ((par.get(0).equals(duplas.get(pessoaQueVaiAndar))) 
			|| (par.get(1).equals(duplas.get(pessoaQueVaiAndar)))) return true;
		
		return false;
	}
	
	private boolean isAlocadoNoParCorreto(String pessoaQueVaiAndar,
			ArrayList<DuplaSemana> duplas) {
		
		List<String> par = pegaPar(pessoaQueVaiAndar);
		if (par == null) return false;
				
		String pessoa = getPar(pessoaQueVaiAndar, duplas);
			
		if ((par.get(0).equals(pessoa)) 
			|| (par.get(1).equals(pessoa))) return true;
		
		return false;
	}
	
	private String getPar(String pessoaQueVaiAndar, ArrayList<DuplaSemana> duplas ) {
		for(DuplaSemana dupla : duplas){
			if (dupla.getNomeDupla1().equals(pessoaQueVaiAndar)){
				return dupla.getNomeDupla2();
			}
		}
		
		return null;			
	}

	private List<String> pegaPar(String pessoaQueVaiAndar) {
		for(List<String> dupla : _posicoes){
			if ((dupla.get(0).equals(pessoaQueVaiAndar)) || (dupla.get(1).equals(pessoaQueVaiAndar)))
				return dupla;
		}
		
		return null;
	}

	private String escolheQuemAnda(List<String> dupla, Integer posicaoQueAnda) {		
		return dupla.get(posicaoQueAnda);
	}
	
}
